﻿using System;
using System.Collections.Generic;
using System.Drawing;

namespace Fifteen
{
    public class TLayout
    {
        public readonly int Columns;
        public readonly int Rows;
        private Point[,] square;
        private TBitmapSplitter splitter;

        public static readonly Point EmptySquare = new Point(-1, -1);

        public TLayout(int columns, int rows, Bitmap bitmap)
        {
            this.Columns = columns;
            this.Rows = rows;
            this.square = new Point[this.Columns, this.Rows];

            for (int y = 0; y < this.Rows; y++)
            {
                for (int x = 0; x < this.Columns; x++)
                {
                    this.square[x, y] = TLayout.EmptySquare;
                }
            }

            this.splitter = new TBitmapSplitter(bitmap);
            this.splitter.Split(this.Columns, this.Rows);
        }

        public Point this[int x, int y]
        {
            get
            {
                return this.square[x, y];
            }
            set
            {
                this.square[x, y] = value;
            }
        }

        public Bitmap GetImageForFinalPosition(int x, int y)
        {
            return this.splitter[this.square[x, y].X, this.square[x, y].Y];
        }

        public Bitmap GetOriginalImage()
        {
            return this.splitter.Original;
        }

        public bool IsComplete()
        {
            bool[,] copy = new bool[this.Columns, this.Rows];
            for (int y = 0; y < this.Rows; y++)
            {
                for (int x = 0; x < this.Columns; x++)
                {
                    copy[x, y] = false;
                }
            }

            foreach (Point p in this.square)
            {
                if ((p.X == TLayout.EmptySquare.X) && (p.Y == TLayout.EmptySquare.Y))
                {
                    return false;
                }
                if (copy[p.X, p.Y])
                {
                    return false;
                }
                copy[p.X, p.Y] = true;
            }

            foreach (bool b in copy)
            {
                if (!b)
                {
                    return false;
                }
            }

            return true;
        }

        public void CreateComplete()
        {
            for (int y = 0; y < this.Rows; y++)
            {
                for (int x = 0; x < this.Columns; x++)
                {
                    this.square[x, y] = new Point(x, y);
                }
            }
        }

        public void CreateRandom()
        {
            List<Point> points = new List<Point>(this.Columns * this.Rows);
            for (int y = 0; y < this.Rows; y++)
            {
                for (int x = 0; x < this.Columns; x++)
                {
                    points.Add(new Point(x, y));
                }
            }

            Random random = new Random(DateTime.Now.Millisecond);

            for (int y = 0; y < this.Rows; y++)
            {
                for (int x = 0; x < this.Columns; x++)
                {
                    int r = random.Next(points.Count);
                    this.square[x, y] = points[r];
                    points.RemoveAt(r);
                }
            }
        }
    }
}
